package com.gxlu.ms.web.filter;

import java.io.IOException;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author andy.lhc
 * @date 2017年12月29日 下午5:14:20
 */
public abstract  class AbstractFilter implements Filter {
    protected final Logger log          = LoggerFactory.getLogger("timeFilterLogger");
    private FilterConfig   filterConfig;

    private boolean  printLog ;

    /**
     * acl排除url
     * 排除一些requrl,如：健康检查url,要排除掉，不要打日志
     */
    private Pattern[] excludePattern = null;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig     = filterConfig;
        this.printLog = Boolean.valueOf(findInitParameter("printLog", "true")).booleanValue();

        if (printLog) {
            log.info("Set eating ServletException to " + printLog);
        }

        String aclUrlExcluded = filterConfig.getInitParameter("exclude_url");
        if (StringUtils.isBlank(aclUrlExcluded)) {
            excludePattern = new Pattern[0];
        } else {
            String[] urlStr = StringUtils.split(aclUrlExcluded,";") ;
            excludePattern = new Pattern[urlStr.length];
            for (int i = 0; i < urlStr.length; i++) {
                excludePattern[i] = Pattern.compile(urlStr[i]);
            }
        }

        init();
    }

    protected void init() throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        if (!(request instanceof HttpServletRequest && response instanceof HttpServletResponse)
            || (request.getAttribute(getClass().getName()) != null)) {

            //过虑乱码等
            chain.doFilter(request, response);
            return;
        }

        try {
            HttpServletRequest  req = (HttpServletRequest) request;
            HttpServletResponse res = (HttpServletResponse) response;

            //排除掉过滤的url
            res.setHeader("Access-Control-Allow-Origin", "*");
            if (checkExclude(req.getRequestURI())) {
                chain.doFilter(request, response);
                return;
            }

            doFilter(req, res, chain);
        } catch (ServletException e) {
            if (printLog) {
                log.error("Failed to execute the filter chain", e);
            } else {
                throw e;
            }
        }
    }

    public abstract void doFilter(HttpServletRequest request, HttpServletResponse response,
                                  FilterChain chain) throws IOException, ServletException;


    public FilterConfig getFilterConfig() {
        return filterConfig;
    }

    @Override
    public void destroy() {
        filterConfig = null;
    }

    public String findInitParameter(String paramName, String defaultValue) {
        // 取filter参数
        String value = trimToNull(getFilterConfig().getInitParameter(paramName));
        // 如果未取到，则取全局参数
        if (value == null) {
            value = trimToNull(getServletContext().getInitParameter(paramName));
        }
        // 如果未取到，则取默认值
        if (value == null) {
            value = defaultValue;
        }

        return value;
    }
    protected String trimToNull(String str) {
        if (str != null) {
            str = str.trim();
            if (str.length() == 0) {
                str = null;
            }
        }
        return str;
    }

    /**
     * 取得request的内容(HTTP方法, URI)
     *
     * @param request HTTP请求
     *
     * @return 字符串
     */
    protected String dumpRequest(HttpServletRequest request) {
        StringBuffer buffer = new StringBuffer(request.getMethod());
        buffer.append(" ").append(request.getRequestURI());
        String queryString = trim(request.getQueryString());
        if (queryString != null) {
            buffer.append("?").append(queryString);
        }
        return buffer.toString();
    }

    public ServletContext getServletContext() {
        return getFilterConfig().getServletContext();
    }

    private  String trim(final String str) {
        final String ts = (str == null ? null : str.trim()) ;
        return (ts == null || ts.length() == 0) ? null : ts;
    }

    /**
     * 检验访问请求是否在exclude列表中
     *
     * @param requestUrl
     * @return
     */
    public final boolean checkExclude(String requestUrl) {
        boolean flag = false;
        if (null == excludePattern || excludePattern.length == 0) {
            return flag;
        }
        for (Pattern pat : excludePattern) {
            if (flag = pat.matcher(requestUrl).matches()) {
                break;
            }
        }
        return flag;
    }



}
